package cn.yh.register.order.service.impl;

import cn.yh.register.common.exception.RegisterException;
import cn.yh.register.common.result.ResultCodeEnum;
import cn.yh.register.enums.PaymentTypeEnum;
import cn.yh.register.enums.RefundStatusEnum;
import cn.yh.register.model.order.OrderInfo;
import cn.yh.register.model.order.PaymentInfo;
import cn.yh.register.model.order.RefundInfo;
import cn.yh.register.order.service.OrderService;
import cn.yh.register.order.service.PaymentService;
import cn.yh.register.order.service.RefundInfoService;
import cn.yh.register.order.service.WeiXinService;
import cn.yh.register.order.utils.ConstantPropertiesUtils;
import cn.yh.register.order.utils.HttpClient;
import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class WeiXinServiceImpl implements WeiXinService {
    @Autowired
    PaymentService paymentService;
    @Autowired
    OrderService orderService;
    @Autowired
    RedisTemplate<String,String > redisTemplate;
    @Autowired
    RefundInfoService refundInfoService;


    /**
     * 对接微信下单接口获取二维码
     * @param orderId 订单id
     * @return 二维码数据
     */
    @Override
    public Map<String, Object> createNative(Long orderId) {
        // 从redis中取出二维码数据
        String mapStr = redisTemplate.opsForValue().get(String.valueOf(orderId));
        if (!StringUtils.isEmpty(mapStr)) {
            log.info("Redis取出二维码数据：{}",mapStr);
            return JSONObject.parseObject(mapStr, Map.class);
        }

        //订单信息
        OrderInfo orderInfo = orderService.getOrderInfo(orderId);
        // 重新生成 订单号
//        String outTradeNo = System.currentTimeMillis() + ""+ new Random().nextInt(100);
//        orderInfo.setOutTradeNo(outTradeNo);
        //保存支付记录
        paymentService.savePaymentInfo(orderInfo, PaymentTypeEnum.WEIXIN.getStatus());

        // 组装数据
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", ConstantPropertiesUtils.APPID);// 公众号appId
        paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);// 商户号
        paramMap.put("out_trade_no", orderInfo.getOutTradeNo());// 商户订单号
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());// 随机字符串
        String body =new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd") + "就诊"+ orderInfo.getDepname();
        paramMap.put("body",body);// 商品描述
        //paramMap.put("total_fee", orderInfo.getAmount().multiply(new BigDecimal("100")).longValue()+"");
        paramMap.put("total_fee", "1");
        paramMap.put("spbill_create_ip", "127.0.0.1");
        paramMap.put("notify_url", "https://2495161sb6.goho.co/api/order/weixinPay/weixinNotify");
        paramMap.put("trade_type", "NATIVE");
        // 设置失效时间 1分钟
        paramMap.put("time_expire",new DateTime().plusMinutes(1).toString("yyyyMMddHHmmss"));
        Map<String,Object> map=null;
        try {
            // 对接微信支付
            HttpClient httpClient =new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            httpClient.setXmlParam(WXPayUtil.generateSignedXml(paramMap,ConstantPropertiesUtils.PARTNERKEY));
            // https 协议
            httpClient.setHttps(true);
            // 请求
            httpClient.post();
            // 获取响应数据
            String xmlContent = httpClient.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(xmlContent);
            log.info("微信下单接口的数据: {}",resultMap.toString());
            if ("SUCCESS".equals(resultMap.get("return_code"))
                    && "SUCCESS".equals(resultMap.get("result_code"))) {
                // 封装返回结果集
                map = new HashMap<>();
                map.put("orderId", orderId);
                map.put("totalFee", orderInfo.getAmount());
                map.put("resultCode", resultMap.get("result_code"));
                map.put("codeUrl", resultMap.get("code_url"));
                // 存入Redis 设置有效时间为1分钟  因为二维码不是自己的 是微信接口提供的 无法控制有效时间
//                redisTemplate.opsForValue().set(String.valueOf(orderId), JSONObject.toJSONString(map),1, TimeUnit.MINUTES);
            }else {
                throw new RegisterException(resultMap.get("return_msg")+" "
                        +resultMap.get("err_code_des"), ResultCodeEnum.FAIL.getCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 对接微信查询接口查询支付状态
     * @param orderId     订单id
     * @param paymentType 支付类型
     * @return 结果数据
     */
    @Override
    public Map<String, String> queryPayStatus(Long orderId, String paymentType) {
        // 查询订单信息
        OrderInfo orderInfo = orderService.getOrderInfo(orderId);
        // 组装数据
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", ConstantPropertiesUtils.APPID);// 公众号appId
        paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);// 商户号
        paramMap.put("out_trade_no", orderInfo.getOutTradeNo());// 商户订单号
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());// 随机字符串

        try {
            // 对接微信接口查询
            HttpClient httpClient =new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            httpClient.setXmlParam(WXPayUtil.generateSignedXml(paramMap,ConstantPropertiesUtils.PARTNERKEY));
            httpClient.setHttps(true); // https 协议
            httpClient.post(); // 请求
            //获取微信返回结果
            String xmlContent = httpClient.getContent();
            return WXPayUtil.xmlToMap(xmlContent);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 对接退款接口
     * @param orderId 退款id
     * @return 是否成功
     */
    @Override
    public Boolean refund(Long orderId) {
        // 订单信息
        OrderInfo orderInfo = orderService.getOrderInfo(orderId);
        // 交易记录 订单号  支付类型
        PaymentInfo paymentInfo = paymentService.getPaymentInfo(orderInfo.getOutTradeNo(), PaymentTypeEnum.WEIXIN.getStatus());
        // 保存退款记录
        RefundInfo refundInfo = refundInfoService.saveRefundInfo(paymentInfo);
        if(refundInfo.getRefundStatus().intValue() == RefundStatusEnum.REFUND.getStatus().intValue()) {
            return true;
        }
        // 组装数据
        Map<String,String> paramMap = new HashMap<>();
        paramMap.put("appid", ConstantPropertiesUtils.APPID);// 公众号appId
        paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);// 商户号
        paramMap.put("out_trade_no", orderInfo.getOutTradeNo());// 商户订单号
        paramMap.put("transaction_id",paymentInfo.getTradeNo()); //微信订单号
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());// 随机字符串
        paramMap.put("out_refund_no","tk"+paymentInfo.getOutTradeNo()); //商户退款单号
        // 总金额
        //paramMap.put("total_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+"");
        // 退款金额
        //paramMap.put("refund_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+"");
        paramMap.put("total_fee","1");
        paramMap.put("refund_fee","1");
        // 对接微信退款接口
        try {
            HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/secapi/pay/refund");
            httpClient.setHttps(true);
            httpClient.setXmlParam(WXPayUtil.generateSignedXml(paramMap,ConstantPropertiesUtils.PARTNERKEY));
            httpClient.setCert(true);// 证书
            httpClient.setCertPassword(ConstantPropertiesUtils.PARTNER);// 证书密码默认为商户号
            httpClient.post();
            // 获取相应数据
            String content = httpClient.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
            if ("SUCCESS".equals(resultMap.get("return_code"))
                    && "SUCCESS".equals(resultMap.get("result_code"))) {
                // 退款成功 更新退款记录
                refundInfo.setCallbackTime(new Date());
                refundInfo.setCallbackContent(resultMap.toString());
                refundInfo.setRefundStatus(RefundStatusEnum.REFUND.getStatus());// 已退款
                refundInfo.setTradeNo(resultMap.get("refund_id"));// 退款流水号
                refundInfoService.updateById(refundInfo);
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
